/*
* Copyright 2010 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/

package org.etherframework.core.util
{
	import flash.events.IEventDispatcher;
	import flash.utils.Dictionary;

	public final class ListenerUtil
	{
		private var dictionary:Dictionary;
		
		public function ListenerUtil(dictionary:Dictionary)
		{
			this.dictionary = dictionary;
		}
		
		public function addListener(type:String, dispatcher:IEventDispatcher, 
									listener:Function, useCapture:Boolean = false, 
									priority:int = 0, useWeakReference:Boolean = false):void
		{
			var dispatcherDict:Dictionary = dictionary[dispatcher] || 
							(dictionary[dispatcher] = new Dictionary());
			var typeDict:Dictionary = dispatcherDict[type] || 
							(dispatcherDict[type] = new Dictionary());
			
			if (typeDict[listener])
				return;
			
			typeDict[listener] = new ListenerInfo(type, dispatcher, listener, useCapture);
			dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
		}
		
		public function removeListener(type:String, dispatcher:IEventDispatcher, 
									   listener:Function, useCapture:Boolean = false):void
		{
			var dispatcherDict:Dictionary = dictionary[dispatcher];
			var typeDict:Dictionary = dispatcherDict[type];
			var info:ListenerInfo = typeDict ? typeDict[listener] : null; 
			
			if (info)
			{
				info.dispatcher.removeEventListener(info.type, info.listener, info.useCapture);
				delete typeDict[listener];
			}
		}
		
		public function hasListener(type:String, dispatcher:IEventDispatcher, listener:Function):Boolean
		{
			return (dictionary[dispatcher] && 
					dictionary[dispatcher][type] &&  
					dictionary[dispatcher][type][listener]);
		}
		
		public function removeListeners(type:String = ""):void
		{
			var info:ListenerInfo;
			var typeDict:Dictionary;
			var dict:Dictionary;
			
			if (type)
			{
				for each(typeDict in dictionary)
				{
					dict = typeDict[type];
					for each (info in dict)
					{
						info.dispatcher.removeEventListener(info.type, info.listener, info.useCapture);
						delete dict[info.listener];
					}
				}
			}
			else
			{
				for each(typeDict in dictionary)
				{
					for each(dict in typeDict)
					{
						for each (info in dict)
						{
							info.dispatcher.removeEventListener(info.type, info.listener, info.useCapture);
							delete dict[info.listener];
						}
					}
				}
			}
		}
	}
}
import flash.events.IEventDispatcher;

final class ListenerInfo
{
	public var type:String;
	
	public var dispatcher:IEventDispatcher;
	
	public var listener:Function;
	
	public var useCapture:Boolean;
	
	public function ListenerInfo(type:String, dispatcher:IEventDispatcher, 
								 listener:Function, useCapture:Boolean)
	{
		this.type = type;
		this.dispatcher = dispatcher;
		this.listener = listener;
		this.useCapture = useCapture;
	}
}